motion controller: Match focus event propagation
authorMatthias Clasen <mclasen@redhat.com>
Fri, 21 Feb 2020 04:20:58 +0000 (23:20 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Fri, 21 Feb 2020 05:51:03 +0000 (00:51 -0500)
Make the crossing event generation for pointer events
match what we do for focus now.

gtk/gtkeventcontrollermotion.c
gtk/gtkmain.c
gtk/gtkprivate.h
gtk/gtkwindow.c

index d0182cbcc0a46618694e561d88003fb95d97ee78..aaea7081d949c77a78a6b340e48e2f472f71e6c0 100644 (file)
@@ -41,9 +41,6 @@ struct _GtkEventControllerMotion
 {
   GtkEventController parent_instance;
 
-  GdkEvent *current_event;
-  const GtkCrossingData *current_crossing;
-
   guint is_pointer             : 1;
   guint contains_pointer       : 1;
 };
@@ -105,18 +102,28 @@ update_pointer_focus (GtkEventController    *controller,
 
   if (crossing->direction == GTK_CROSSING_IN)
     {
+     if (crossing->new_descendent != NULL)
+        {
+          contains_pointer = TRUE;
+        }
       if (crossing->new_target == widget)
-        is_pointer = TRUE;
-      if (crossing->new_target != NULL)
+        {
+          contains_pointer = TRUE;
+          is_pointer = TRUE;
+        }
+    }
+  else
+    {
+      if (crossing->new_descendent != NULL ||
+          crossing->new_target == widget)
         contains_pointer = TRUE;
+      is_pointer = FALSE;
     }
 
   if (motion->contains_pointer != contains_pointer)
     {
-      if (contains_pointer)
-        enter = TRUE;
-      else
-        leave = TRUE;
+      enter = contains_pointer;
+      leave = !contains_pointer;
     }
 
   if (leave)
@@ -145,16 +152,8 @@ gtk_event_controller_motion_handle_crossing (GtkEventController    *controller,
                                              double                 x,
                                              double                 y)
 {
-  GtkEventControllerMotion *motion = GTK_EVENT_CONTROLLER_MOTION (controller);
-
-  if (crossing->type != GTK_CROSSING_POINTER)
-    return;
-
-  motion->current_crossing = crossing;
-
-  update_pointer_focus (controller, crossing, x, y);
-
-  motion->current_crossing = NULL;
+  if (crossing->type == GTK_CROSSING_POINTER)
+    update_pointer_focus (controller, crossing, x, y);
 }
 
 static void
index 21ea620b7ec2b929c7463c989bfb20c8d1612044..8ca682925fea5b604ee784f66ad7e77110c7d75e 100644 (file)
@@ -1312,20 +1312,52 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
                                 GdkCrossingMode  mode)
 {
   GtkCrossingData crossing;
+  GtkWidget *ancestor;
   GtkWidget *widget;
   GList *list, *l;
   double x, y;
+  GtkWidget *prev;
+  gboolean seen_ancestor;
+
+  if (old_target && new_target)
+    ancestor = gtk_widget_common_ancestor (old_target, new_target);
+  else
+    ancestor = NULL;
 
   crossing.type = GTK_CROSSING_POINTER;
   crossing.mode = mode;
   crossing.old_target = old_target;
+  crossing.old_descendent = NULL;
   crossing.new_target = new_target;
+  crossing.new_descendent = NULL;
 
   crossing.direction = GTK_CROSSING_OUT;
 
+  prev = NULL;
+  seen_ancestor = FALSE;
   widget = old_target;
   while (widget)
     {
+      crossing.old_descendent = prev;
+      if (seen_ancestor)
+        {
+          crossing.new_descendent = new_target ? prev : NULL;
+        }
+      else if (widget == ancestor)
+        {
+          GtkWidget *w;
+
+          crossing.new_descendent = NULL;
+          for (w = new_target; w != ancestor; w = gtk_widget_get_parent (w))
+            crossing.new_descendent = w;
+
+          seen_ancestor = TRUE;
+        }
+      else
+        {
+          crossing.new_descendent = NULL;
+        }
+      check_crossing_invariants (widget, &crossing);
       translate_event_coordinates (event, &x, &y, widget);
       gtk_widget_handle_crossing (widget, &crossing, x, y);
       gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_PRELIGHT);
@@ -1333,18 +1365,38 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
     }
 
   list = NULL;
-  widget = new_target;
-  while (widget)
-    {
-      list = g_list_prepend (list, widget);
-      widget = gtk_widget_get_parent (widget);
-    }
+  for (widget = new_target; widget; widget = gtk_widget_get_parent (widget))
+    list = g_list_prepend (list, widget);
 
   crossing.direction = GTK_CROSSING_IN;
 
+  seen_ancestor = FALSE;
   for (l = list; l; l = l->next)
     {
       widget = l->data;
+      if (l->next)
+        crossing.new_descendent = l->next->data;
+      else
+        crossing.new_descendent = NULL;
+      if (seen_ancestor)
+        {
+          crossing.old_descendent = NULL;
+        }
+      else if (widget == ancestor)
+        {
+          GtkWidget *w;
+
+          crossing.old_descendent = NULL;
+          for (w = old_target; w != ancestor; w = gtk_widget_get_parent (w))
+            crossing.old_descendent = w;
+
+          seen_ancestor = TRUE;
+        }
+      else
+        {
+          crossing.old_descendent = old_target ? crossing.new_descendent : NULL;
+        }
+
       translate_event_coordinates (event, &x, &y, widget);
       gtk_widget_handle_crossing (widget, &crossing, x, y);
       gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
index 13bbc058e125271fe22e936287901b6bf3f80ea4..9e4e73a11fd20f1eb30603da284570931622423b 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "gtkcsstypesprivate.h"
 #include "gtktexthandleprivate.h"
+#include "gtkeventcontrollerprivate.h"
 
 G_BEGIN_DECLS
 
@@ -97,6 +98,11 @@ gboolean   gtk_propagate_event          (GtkWidget       *widget,
                                          GdkEvent        *event);
 void       gtk_main_do_event       (GdkEvent           *event);
 
+GtkWidget *gtk_get_event_widget         (GdkEvent  *event);
+
+void check_crossing_invariants (GtkWidget       *widget,
+                                GtkCrossingData *crossing);
+
 gdouble _gtk_get_slowdown (void);
 void    _gtk_set_slowdown (gdouble slowdown_factor);
 
index 9a60d813d1286633aca41f3053198f434f1dfbac..7b1c9c2f6dac2c7866599b1cb39de0c74f1bbb43 100644 (file)
@@ -6352,10 +6352,11 @@ gtk_window_move_focus (GtkWidget        *widget,
     gtk_window_set_focus (GTK_WINDOW (widget), NULL);
 }
 
-static void
+void
 check_crossing_invariants (GtkWidget *widget,
                            GtkCrossingData *crossing)
 {
+#ifdef G_ENBABLE_DEBUG
   if (crossing->old_target == NULL)
     g_assert (crossing->old_descendent == NULL);
   else if (crossing->old_descendent == NULL)
@@ -6376,6 +6377,7 @@ check_crossing_invariants (GtkWidget *widget,
       g_assert (gtk_widget_is_ancestor (crossing->new_descendent, widget));
       g_assert (crossing->new_target == crossing->new_descendent || gtk_widget_is_ancestor (crossing->new_target, crossing->new_descendent));
     }
+#endif
 }
 
 static void